package com.scs.application.modules.design.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.design.dto.CreateCRUDFileDTO;
import com.scs.application.modules.design.dto.CreateFrontFileDTO;
import com.scs.application.modules.design.dto.TableColumnDTO;
import com.scs.application.modules.design.service.ProgramService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

@Service
@Configuration
@Slf4j
public class ProgramServiceImpl implements ProgramService {
    @Autowired
    private JdbcTemplate jdbcTemplateDefault;

    @Override
    public Boolean createCRUD(CreateCRUDFileDTO para) {
        return true;
    }

    @Override
    public Boolean createFront(CreateFrontFileDTO para) {
        return true;
    }

    @Override
    public Boolean createAll(CreateCRUDFileDTO crudFileDTO) {
        String entityColumn = "",formItem ="";

        List<TableColumnDTO> columnList = jdbcTemplateDefault.query(
                "select concat(table_name,'_',column_name) as  tablecolumn, table_name as tablename,column_name as columnname,data_type as datatype,character_maximum_length as maxlen,column_comment as columncomment " +
                        "from INFORMATION_SCHEMA.Columns where  table_schema=(select database()) and table_name ='"+crudFileDTO.getTableName().toLowerCase()+"'", new BeanPropertyRowMapper<TableColumnDTO>(TableColumnDTO.class));;

        if (columnList != null && columnList.size() > 0) {
            String remark = "",columnnamel="",columnnameup="",columnType="",formItemType="";
            boolean isBool= false,isNum= false,isDate = false;
            List<String> entityColNot = Arrays.asList("id","creator","gmtCreate","modifier","gmtModified","flowStatus","flowModified","flowModifier","flowModifierCode","printTime","flagPrint","snum","flowCloseRemark");
            for (TableColumnDTO column : columnList) {
                remark = column.getColumncomment();
                if (StringUtils.isBlank(remark)) {
                    remark = column.getColumnname();
                }
                columnnamel = column.getColumnname().toLowerCase();
                columnnameup = StringUtils.underline2Camel(column.getColumnname(), true);
                if (StringUtils.isNotBlank(remark) && remark.indexOf("|") !=0) {
                    remark = remark.split("\\|")[0];
                }
                isBool= false;
                isNum= false;
                isDate = false;
                if (columnnamel.indexOf("flag") != -1) {
                    columnType = "Boolean";
                    formItemType = " :type=\"constCommon.formItemType.switch.name\" ";
                } else if (columnnamel.indexOf("sku") != -1 || columnnamel.indexOf("amount") != -1 || columnnamel.indexOf("aount") != -1 ){
                    isNum = true;
                    columnType = "Double";
                    formItemType = " :type=\"constCommon.formItemType.inputNumber.name\" ";

                } else if (columnnamel.indexOf("date") != -1 || columnnamel.indexOf("time") != -1 ){
                    isDate = true;
                    columnType = "Date";
                    formItemType = " :type=\"constCommon.formItemType.datePicker.name\" ";

                } else{
                    columnType = "String";
                    formItemType = " ";
                }

                if (!entityColNot.contains(columnnameup)) {
                    entityColumn+= StrUtil.format("    //{}",remark);
                    entityColumn+= GlobalConsts.SpecialSymbol.WRAP;
                    entityColumn+= StrUtil.format("    private {} {};",columnType, columnnameup);
                    entityColumn+= GlobalConsts.SpecialSymbol.WRAP;
                    entityColumn+= GlobalConsts.SpecialSymbol.WRAP;
                }

                if (!entityColNot.contains(columnnameup)) {
                    formItem+=StrUtil.format("              <customFormItem label=\"{}\" name=\"{}\" :parent=\"_self\" :form=\"form\" {}/>",remark, columnnameup,formItemType);
                    formItem+= GlobalConsts.SpecialSymbol.WRAP;
                    formItem+= GlobalConsts.SpecialSymbol.WRAP;
                }
            }
        }
        // 后端
        if (StringUtils.isNotBlank(crudFileDTO.getBuildPathServer())) {
            File dirModelServer = null;
            try {
                dirModelServer = ResourceUtils.getFile("classpath:templates/model_server");
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            File dirServerTo  = new File(crudFileDTO.getBuildPathServer());
            creatFile(crudFileDTO,dirModelServer,dirServerTo,entityColumn,formItem);
        }


        // 前端
        if (StringUtils.isNotBlank(crudFileDTO.getBuildPathWeb())) {
            File dirModelWeb = null;
            try {
                dirModelWeb = ResourceUtils.getFile("classpath:templates/model_web");
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            File dirWebTo  = new File(crudFileDTO.getBuildPathWeb() +"/" + crudFileDTO.getTableName().toLowerCase());
            creatFile(crudFileDTO,dirModelWeb,dirWebTo,entityColumn,formItem);
        }

        return false;
    }

    private void creatFile(CreateCRUDFileDTO param,File dirFrom,File dirTo,String entityColumn,String formItem) {
        Collection<File> fileList =  FileUtils.listFiles(dirFrom, FileFilterUtils.fileFileFilter(), DirectoryFileFilter.INSTANCE);
        BusinessException.throwErrorIf(fileList == null || fileList.size() == 0, "未找到模板文件");

        String tableName = param.getTableName();
        // 表名 大写
        String tableu = StringUtils.underline2Camel(tableName, false);

        //表名 小写
        String tablel = tableName.toLowerCase();
        // 模板文件后缀
        String nameEnd=".model";
        //类访问路径
        String pathClass="/" + tableName.toLowerCase().replaceAll("_","/");

        try {
            // 创建目标路径
            FileUtils.forceMkdirParent(dirTo);

            // 复制所有文件
            FileUtils.copyDirectory(dirFrom,dirTo);

            List<File> fileNewList =  FileUtil.loopFiles(dirTo);
            String nameNew;
            List<String> fileLineList,fileLineListNew;
            for(File fileNew : fileNewList) {
                // 替换文件内容
                fileLineList = FileUtil.readLines(fileNew, CharsetUtil.UTF_8);
                fileLineListNew = new ArrayList<>();
                for(String line: fileLineList) {
                    line = line.replaceAll("#tableu#",tableu);
                    line = line.replaceAll("#tablel#",tablel);
                    line = line.replaceAll("#pathClass#",pathClass);
                    line = line.replaceAll("#viewName#",param.getViewName());
                    line = line.replaceAll("#viewKey#",param.getViewKey());
                    line = line.replaceAll("#basePackageName#",param.getBasePackageName());
                    line = line.replaceAll("#entityColumn#",entityColumn);
                    line = line.replaceAll("#formItem#",formItem);

                    fileLineListNew.add(line);
                }
                FileUtil.writeLines(fileLineListNew,fileNew, CharsetUtil.UTF_8);

                // 替换文件名
                nameNew = fileNew.getName().replaceAll(nameEnd,"");
                nameNew = nameNew.replaceAll("tableu",tableu);
                nameNew = nameNew.replaceAll("tablel",tablel);
                FileUtil.rename(fileNew,nameNew, true);
            }
        } catch (IOException e) {
            log.error("文件拷贝失败",e);
            throw new BusinessException("文件拷贝失败");
        }
    }
}
